class SocketUtil {
  /**
   * 开始debug
   * @type {boolean}
   */
  static debug = true;
  /**
   * 重连计时器 （5秒）
   * @type {number}
   */
  static RE_CONNECT_TIME = 5 * 1000;
  /**
   * 每段时间发送一次心跳包 这里设置为20s
   * @type {number}
   */
  static HEART_TIMEOUT = 20 * 1000;
  /**
   * 心跳发送/返回的信息 服务器和客户端收到的信息内容如果如下 就识别为心跳信息 不要做业务处理
   * @type {string}
   */
  static CHECK_MSG = "heartbeat";
  /**
   * 打印日志
   * @param msg
   */
  static log(...msg) {
    if (SocketUtil.debug) {
      console.log(...msg)
    }
  }
  /**
   * 解析Unicode
   */
  decodeUnicode(str) {
    str = str.replace(/\\/g, "%");
    //转换中文
    str = unescape(str);
    //将其他受影响的转换回原来
    str = str.replace(/%/g, "\\");
    //对网址的链接进行处理
    str = str.replace(/\\/g, "");
    return str;
  }
}

/**
 * IM 使用Scoket
 */
export class IMScoket {
  constructor(options = {}) {
    this.options = Object.assign({
      // 地址
      ws: ""
      // 消息接收
      ,onOpenListener: ()=> {}
      // 关闭
      ,onCloseListener: ()=> {}
      // 发送消息
      ,onSendListener: (data)=> {}
      // 消息接收
      ,onReceivedListener: (message)=> {}
    }, options || {});
    this.websock = null;
    this.rec = null; //断线重连后，延迟5秒重新创建WebSocket连接  rec用来存储延迟请求的代码
    this.isConnect = false; //连接标识 避免重复连接
    this.heartTimeoutObj = null; //延时发送消息对象（启动心跳新建这个对象，收到消息后重置对象）
  }

  /**
   * 创建socket
   * ws: eg: 192.168.1.22:18308/chat
   */
  createWebSocket() {
    try {
      SocketUtil.log("链接地址");
      if (!this.options.ws) {
        return new Error("地址不能为null")
      }
      let ws = this.options.ws;
      this.websock = new WebSocket("ws://" + ws);
      this.initWebSocket(); //初始化websocket连接
    } catch (e) {
      SocketUtil.log("尝试创建连接失败");
      this.reConnect(); //如果无法连接上webSocket 那么重新连接！可能会因为服务器重新部署，或者短暂断网等导致无法创建连接
    }
  }

  /**
   * 初始化websocket
   */
  initWebSocket() {
    // ws地址 -->这里是你的请求路径
    // let uName = localStorage.getItem("uName")
    // var ws = "ws://192.168.1.22:18308/chat?username=" + uName
    // websock = new WebSocket(ws)
    const _this = this;

    this.websock.onopen = function () {
      _this.onOpen()
      // heartCheck.start();
    };

    this.websock.onclose = function (e) {
      _this.onClose(e)
    };

    this.websock.onmessage = function (e) {
      console.log("onmessage", e);
      _this.onMessage(e)
    };

    // 连接发生错误的回调方法
    this.websock.onerror = function () {
      SocketUtil.log('WebSocket连接发生错误');
      _this.isConnect = false; //连接断开修改标识
      _this.reConnect(); //连接错误 需要重连
    }
  }

  /**
   * 重连函数
   */
  reConnect = () => {
    SocketUtil.log("尝试重新连接");
    if (this.isConnect) return; //如果已经连上就不在重连了
    this.rec && clearTimeout(this.rec);
    const _this = this;
    this.rec = setTimeout(function () { // 延迟5秒重连  避免过多次过频繁请求重连
      _this.closeWebSocket();
      _this.createWebSocket();
    }, SocketUtil.RE_CONNECT_TIME);
  };

  /**
   * 心跳开始
   */
  heartStart() {
    this.timeoutObj = setTimeout(function () {
      if (this.isConnect) this.websock.send(SocketUtil.CHECK_MSG);
    }, SocketUtil.HEART_TIMEOUT);
  }

  /**
   * 重置心跳
   */
  heartReset() {
    clearTimeout(this.timeoutObj);
    this.heartStart();
  }

  /**
   * 关闭scoket
   */
  closeWebSocket() {
    if (this.websock) {
      SocketUtil.log("关闭连接");
      this.websock.close();
    }
  }

  /**
   * 创建 websocket 连接
   * @param e
   */
  onOpen() {
    SocketUtil.log('连接成功');
    if (this.options.onOpenListener) {
      this.options.onOpenListener()
    }
  }

  /**
   * 关闭
   */
  onClose(e) {
    this.isConnect = false ; //断开后修改标识
    SocketUtil.log('connection closed (' + e.code + ')')
    if (this.options.onCloseListener) {
      this.options.onCloseListener()
    }
  }

  /**
   * 发送信息
   * @param agentData 发送的数据
   * @param callback 回调函数
   */
  send(agentData) {
    const _this = this;
    // console.log(globalCallback)
    if (this.websock.readyState === this.websock.OPEN) {
      // 若是ws开启状态
      _this.onSend(agentData)
    } else if (this.websock.readyState === this.websock.CONNECTING) {
      // 若是 正在开启状态，则等待1s后重新调用
      setTimeout(function () {
        _this.send(agentData)
      }, 1000)
    } else {
      // 若未开启 ，则等待1s后重新调用
      setTimeout(function () {
        _this.send(agentData)
      }, 1000)
    }
  }

  /**
   * 数据发送
   * @param agentData
   */
  onSend(agentData) {
    // let data = JSON.stringify(agentData);
    let data = agentData;
    this.websock.send(data);
    if (this.options.onSendListener) {
      this.options.onSendListener(data)
    }
  }

  /**
   * 数据接收
   * @param e
   */
  onMessage(e) {
    // let data = JSON.parse(SocketUtil.decodeUnicode(e.data))
    // let data = JSON.parse(e.data);
    let data = e.data;
    if (!data) {
      SocketUtil.log("心跳：" + data);
      this.heartReset();
    } else {
      if (this.options.onReceivedListener) {
        this.options.onReceivedListener(data)
      }
    }
  }
}

